package com.gitee.slowcreator.http.executor;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Singleton;
import cn.hutool.core.util.ServiceLoaderUtil;
import cn.hutool.core.util.StrUtil;
import com.gitee.slowcreator.http.config.ScHttpConfig;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * http 执行器工厂
 * 参考hutool
 *
 * @author zxw
 * @date 2023/1/6 下午9:17
 */
@Slf4j
public class HttpExecutorFactory {

    /**
     * 根据用户引入的jar，自动创建对应的http执行器对象<br>
     * 获得的是单例的HttpExecutor
     *
     * @return 单例的HttpExecutor
     */
    public static HttpExecutor get(){

        return Singleton.get(HttpExecutor.class.getName(), HttpExecutorFactory::create);
    }

    /**
     * 根据用户引入的http请求jar，自动创建对应的对象
     *
     * @return {@link HttpExecutor}
     */
    public static HttpExecutor create() {
        final HttpExecutor engine = doCreate();
        log.info("Use [{}] http executor As Default.", StrUtil.removeSuffix(engine.getClass().getSimpleName(), "Executor"));
        return engine;
    }

    /**
     * 根据用户引入的分词http请求jar，自动创建对应的对象
     *
     * @return {@link HttpExecutor}
     */
    private static HttpExecutor doCreate() {

        ServiceLoader<HttpExecutor> serviceLoader = ServiceLoaderUtil.load(HttpExecutor.class);
        Iterator<HttpExecutor> iterator = serviceLoader.iterator();
        String fixedHttp = ScHttpConfig.getFixedHttp();
        while (iterator.hasNext()) {
            try {
                HttpExecutor httpExecutor = iterator.next();
                if (StrUtil.isBlank(fixedHttp)) {
                    return httpExecutor;
                }
                if (StrUtil.equals(httpExecutor.executorType(), fixedHttp)) {
                    return httpExecutor;
                }
            } catch (ServiceConfigurationError ignore) {
                // ignore
            }
        }

        if (StrUtil.isBlank(fixedHttp)) {
            throw new RuntimeException("未找到http执行器依赖，请确定是否引入了指定依赖！");
        } else {
            throw new RuntimeException(
                    StrUtil.format("固定http执行器类型:[{}]未找到,请确定是否引入了指定依赖！", fixedHttp)
            );
        }
    }
}
